import 'package:casdon/core/logger/log.dart';
import 'package:casdon/modules/lifeCircle/data/model/life_topic_module.dart';
import 'package:casdon/modules/lifeCircle/domain/states/life_topic_search_state.dart';
import 'package:casdon/modules/lifeCircle/domain/usecase/life_topic_search_usecase.dart';
import 'package:casdon/modules/lifeCircle/providers/life_provider.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

class LifeTopicSearchNotifier
    extends AutoDisposeFamilyAsyncNotifier<LifeTopicSearchState, String> {
  late final String keyword;
  final int pageSize = 10;
  bool _isLoadingMore = false;
  bool _isRefreshing = false;

  bool get hasMore {
    final currentState = state.valueOrNull;
    if (currentState == null) return true;
    if (currentState.totalSize == 0) return true;
    return currentState.data.length < currentState.totalSize;
  }

  void updateFollowStatusByUser(String userId, bool isFollowed) {
    final current = state.valueOrNull;
    if (current == null || current.data.isEmpty) {
      return;
    }

    var hasChanges = false;
    final updated = current.data.map((topic) {
      if (topic.userId == userId && topic.isFollow != isFollowed) {
        hasChanges = true;
        return topic.copyWith(isFollow: isFollowed);
      }
      return topic;
    }).toList();

    if (hasChanges) {
      state = AsyncValue.data(current.copyWith(data: updated));
    }
  }

  void updateTopicLikeStatus(
    String topicId,
    bool isLiked,
    int newLikesCount,
  ) {
    final current = state.valueOrNull;
    if (current == null || current.data.isEmpty) {
      return;
    }

    var hasChanges = false;
    final updated = current.data.map((topic) {
      if (topic.id == topicId) {
        hasChanges = true;
        return topic.copyWith(
          isLike: isLiked,
          likes: newLikesCount,
        );
      }
      return topic;
    }).toList();

    if (hasChanges) {
      state = AsyncValue.data(current.copyWith(data: updated));
    }
  }

  bool get isLoadingMore => _isLoadingMore;
  bool get isRefreshing => _isRefreshing;

  @override
  Future<LifeTopicSearchState> build(String arg) async {
    ref.onDispose(() {
      Log.d('LifeTopicSearchNotifier for $arg 已被释放！');
    });
    if (arg.isEmpty) {
      return LifeTopicSearchState.initial();
    }
    keyword = arg;
    return await _fetchData();
  }

  Future<void> refresh() async {
    if (_isRefreshing) return;
    _isRefreshing = true;

    try {
      _resetPageNum();
      final result = await _safeFetchData();
      state = AsyncValue.data(result);
    } catch (e, st) {
      Log.e("LifeTopicSearch refresh 错误", e, st);
      state = AsyncValue.error(e, st);
    } finally {
      _isRefreshing = false;
    }
  }

  void _resetPageNum() {
    final currentState = state.valueOrNull;
    if (currentState != null) {
      state = AsyncValue.data(currentState.copyWith(pageNum: 0));
    }
  }

  Future<void> loadMore() async {
    // 如果正在刷新，不要执行加载更多
    if (_isRefreshing || _isLoadingMore || !hasMore) return;

    _isLoadingMore = true;

    try {
      final currentState = state.valueOrNull;
      if (currentState == null) return;

      final nextPage = await _fetchData();

      if (nextPage.data.isEmpty) {
      } else {
        // 去重：基于 id
        final existingIds = currentState.data.map((e) => e.id).toSet();
        final newData = nextPage.data
            .where((item) => !existingIds.contains(item.id))
            .toList();

        if (newData.isNotEmpty) {
          final merged = LifeTopicSearchState(
            data: [...currentState.data, ...newData],
            pageNum: nextPage.pageNum,
            totalSize: nextPage.totalSize,
          );
          state = AsyncValue.data(merged);
        } else {}
      }
    } catch (e, st) {
      Log.e("LifeTopicSearch loadMore 错误", e, st);
    } finally {
      _isLoadingMore = false;
    }
  }

  Future<LifeTopicSearchState> _fetchData() async {
    LifeTopicSearchState? stateData = state.valueOrNull;
    stateData ??= LifeTopicSearchState.initial();

    List<LifeTopicModule> oldData = List.of(stateData.data);
    final pageNum = stateData.pageNum + 1;
    final ret = await ref
        .read(lifeTopicSearchUsecaseProvider)
        .execute(searchText: keyword, pageNum: pageNum, pageSize: pageSize);

    if (ret.rows == null || ret.rows!.isEmpty) {
      return stateData;
    }

    final newTopics = LifeTopicModule.listFromApi(ret.rows!);
    if (pageNum == 1) {
      oldData = newTopics;
    } else {
      oldData.addAll(newTopics);
    }
    return stateData.copyWith(
      data: oldData,
      pageNum: pageNum,
      totalSize: ret.total,
    );
  }

  Future<void> clearData() async {
    state = AsyncValue.data(LifeTopicSearchState.initial());
  }

  Future<LifeTopicSearchState> _safeFetchData() async {
    try {
      return await _fetchData();
    } catch (e, st) {
      Log.e("LifeTopicSearch _safeFetchData 错误", e, st);
      return LifeTopicSearchState.initial();
    }
  }
}

final lifeTopicSearchUsecaseProvider = Provider(
  (ref) => LifeTopicSearchUsecase(ref.read(lifeRepository)),
);

final lifeTopicSearchProvider =
    AutoDisposeAsyncNotifierProviderFamily<
      LifeTopicSearchNotifier,
      LifeTopicSearchState,
      String
    >(LifeTopicSearchNotifier.new);
